package com.goatstone.client;

import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

class ColorPicker extends Composite{
	private int[] selectedColor;
	private VerticalPanel swatchPanel, selectedColorPanel;
	private HorizontalPanel mainPanel;
	MainWidgetComposite mwc;
	ColorPicker(	MainWidgetComposite mwc ){
		this.mwc = mwc;
		selectedColor = new int[3];

		mainPanel = new HorizontalPanel();
		DOM.setElementAttribute(mainPanel.getElement(), "id", "goat-cp");

		swatchPanel = new VerticalPanel();			

		selectedColorPanel = new VerticalPanel();
		DOM.setElementAttribute(selectedColorPanel.getElement(), "class", "selectedColor");
		selectedColorPanel.add(new HTML("&nbsp;"));

		generatePanel();
			
		mainPanel.add(selectedColorPanel);
		mainPanel.add(swatchPanel);

		initWidget(mainPanel);
	}
	
	public int[] getSelectedColor(){			
		return selectedColor;
	}
	private void setSelectedColor( int[] color ){
		DOM.setStyleAttribute(selectedColorPanel.getElement(),"backgroundColor","rgb("+color[0]+","+color[1]+","+color[2]+")");
		selectedColor = color;
	}
	// create three strips of colors
	private void generatePanel(){
		HorizontalPanel light, medium,  grey;
		light = new HorizontalPanel();
		medium = new HorizontalPanel();
		grey = new  HorizontalPanel();		
		for(int i=0; i<100; i+=5){
			Swatch swatch;
			float hue = (float) (new Float(i)* 3.6);
			// full value bar	
			int[] colorTemp;
			colorTemp = new int[3];
			colorTemp = hSVToRGB(new Float(hue),new Float(100),new Float(100));
			swatch = new Swatch(  colorTemp );
			light.add(swatch);
			// medium value bar			
			colorTemp = hSVToRGB(new Float(hue),new Float(100),new Float(80));
			swatch = new Swatch(colorTemp);
			medium.add(swatch);
			// grey scale bar			
			colorTemp = hSVToRGB(new Float(0),new Float(0),new Float(i));
			swatch = new Swatch(colorTemp);
			grey.add(swatch);
		}
		swatchPanel.add(light);
		swatchPanel.add(medium);
		swatchPanel.add(grey);
	}

	private class Swatch extends Widget {  
		private HandlerRegistration registration;  	
		final DivElement element;
		private int[] color;
		Swatch( int[] color ) {  
			this.color = color;
			element = Document.get().createDivElement();  			   
			element.setInnerText(".");  
			setElement(element);  
			element.getStyle().setProperty("color", "rgb("+color[0]+","+color[1]+","+color[2]+")");
			element.getStyle().setProperty("backgroundColor", "rgb("+color[0]+","+color[1]+","+color[2]+")");
			setStylePrimaryName("swatch");
		}  			   		
		@Override  
		protected void onLoad() {  
			super.onLoad();  			   
			setSelectedColor( new int[] {50,0,0} );
			registration = addDomHandler(new ClickHandler() {  
				public void onClick(final ClickEvent event) {  
					setSelectedColor( color );
					mwc.setTextBoxFontColor( color );
					mwc.setTextBoxFocus();
				}  
			}, ClickEvent.getType());  
		}  			   
		@Override  
		protected void onUnload() {  
			super.onUnload();  			   
			registration.removeHandler();  
			registration = null;  
		}  			   
	}  	

	/**
	 * HSV to RGB color conversion
	 * Ported from the algorithm by Eugene Vishnevsky at:
	 * http://www.cs.rit.edu/~ncs/color/t_convert.html
	 */
	private int[] hSVToRGB(float h, float s, float v) {
		float r, g, b;
		int i;
		float f, p, q, t;

		h = Math.max(0, Math.min(360, h));
		s = Math.max(0, Math.min(100, s));
		v = Math.max(0, Math.min(100, v));
		// convert 0-100  to range 0-1
		s /= 100;
		v /= 100;
		if(s == 0) {
			// Achromatic (grey)
			r = g = b = v;
			return new int[] {(int)(r*255),(int)(g*255),(int)(b*255)};
			//			return (int)(r*255) +","+(int)(g*255)+","+(int)(b*255);
		}
		h /= 60; // sector 0 to 5
		i = (int)Math.floor(h);
		f = h - i; // factorial part of h
		p = v * (1 - s);
		q = v * (1 - s * f);
		t = v * (1 - s * (1 - f));
		switch(i) {
		case 0:
			r = v;
			g = t;
			b = p;
			break;
		case 1:
			r = q;
			g = v;
			b = p;
			break;
		case 2:
			r = p;
			g = v;
			b = t;
			break;
		case 3:
			r = p;
			g = q;
			b = v;
			break;
		case 4:
			r = t;
			g = p;
			b = v;
			break;
		default: // case 5:
			r = v;
		g = p;
		b = q;
		}
		return new int[] {(int)(r*255),(int)(g*255),(int)(b*255)};
	}	
}
